//+------------------------------------------------------------------+
//|                                                  DualMA_EA.mq5   |
//|                        Copyright 2023, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.01"  // 版本号更新
#include <Trade\Trade.mqh>

input int      FastMAPeriod = 1;          // 快线周期
input int      SlowMAPeriod = 3;         // 慢线周期
input double   Lots = 0.01;                 // 交易手数
input int      StopLossPoints = 100;       // 止损点数
input int      TakeProfitPoints = 200;     // 止盈点数
input ulong    MagicNumber = 12345;       // EA魔术号
bool triggered = false; // 防止重复触发标志

int ssfastMA, fastMA, slowMA;
datetime lastBarTime;
CTrade trade;


//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    trade.SetExpertMagicNumber(MagicNumber);

    // 设置1秒定时器
   EventSetTimer(1);
  // ssfastMA = iMA(_Symbol, PERIOD_CURRENT, ssMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   fastMA = iMA(_Symbol, PERIOD_CURRENT, FastMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   slowMA = iMA(_Symbol, PERIOD_CURRENT, SlowMAPeriod, 0, MODE_SMA, PRICE_CLOSE);
   trade.SetExpertMagicNumber(MagicNumber);
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   EventKillTimer(); // 删除定时器
}

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
{
   datetime currentTime = TimeCurrent();                // 获取当前服务器时间
   datetime nextBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);   // 计算下一根K线开始时间
   int remainingSeconds = (int)(nextBarTime - currentTime); // 计算剩余秒数
   Print(remainingSeconds,"====计算剩余秒数=",nextBarTime);
   // 当剩余5秒且未触发过时执行
   if(remainingSeconds == -20 && !triggered)
   {
      Print(remainingSeconds,"====计算剩余秒数=",nextBarTime);
      triggered = true; // 设置触发标志
   }

   // 当剩余时间超过5秒时重置触发标志
   if(remainingSeconds > -20)
   {
      triggered = false;
   }
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
     // 检查时间条件（K线结束前5秒内）
   //if(!triggered) return;
   // 检查新K线
   datetime currentBarTime = iTime(_Symbol, _Period, 0);
   if(lastBarTime == currentBarTime) return;
   lastBarTime = currentBarTime;

   // 获取均线值
   double  fastMAValues[3], slowMAValues[3];
   //CopyBuffer(ssfastMA, 0, 1, 2, ssfastMAValues);
   CopyBuffer(fastMA, 0, 1, 2, fastMAValues);
   CopyBuffer(slowMA, 0, 1, 2, slowMAValues);
   ArraySetAsSeries(fastMAValues, true);
   ArraySetAsSeries(slowMAValues, true);
   
   
   // 检查交叉信号
   bool goldenCross = (fastMAValues[1] > slowMAValues[1]) && (fastMAValues[0] <= slowMAValues[0]);
   bool deathCross = (fastMAValues[1] < slowMAValues[1]) && (fastMAValues[0] >= slowMAValues[0] && (fastMAValues[0]-slowMAValues[0]));
  
   
   
   // 处理交易信号
   if(goldenCross)
   {
      // CloseAllPositions();  // 平掉所有仓位
      // OpenBuyPosition();
   }
   else if(deathCross)
   {
      CloseAllPositions();  // 平掉所有仓位
      OpenSellPosition();
   }

   // 检查移动止损条件
   CheckTrailingStop();
}

//+------------------------------------------------------------------+
//| 开多单（增加持仓检查）                                           |
//+------------------------------------------------------------------+
void OpenBuyPosition()
{
   // 检查是否已有持仓
   if(PositionSelect(_Symbol)) return;

   double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double sl = price - StopLossPoints * _Point;
   double tp = price + TakeProfitPoints * _Point;
   
   trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, Lots, price, sl, tp, "Golden Cross Entry");
}

//+------------------------------------------------------------------+
//| 开空单（增加持仓检查）                                           |
//+------------------------------------------------------------------+
void OpenSellPosition()
{
   // 检查是否已有持仓
   if(PositionSelect(_Symbol)) return;

   double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double sl = price + StopLossPoints * _Point;
   double tp = price - TakeProfitPoints * _Point;
   
   trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, Lots, price, sl, tp, "Death Cross Entry");
}


//+------------------------------------------------------------------+
//| 平所有仓位                                                       |
//+------------------------------------------------------------------+
void CloseAllPositions()
{
   for(int i = PositionsTotal()-1; i >= 0; i--)
   {
      ulong ticket = PositionGetTicket(i);
      if(PositionGetString(POSITION_SYMBOL) == _Symbol && 
         PositionGetInteger(POSITION_MAGIC) == MagicNumber)
      {
         double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
         double currentSL = PositionGetDouble(POSITION_SL);
         double currentTP = PositionGetDouble(POSITION_TP);
         double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double requiredPrice = openPrice + openPrice * 0.5;
        

         if(currentPrice/requiredPrice >= 1.5)
         {
            trade.PositionClose(ticket);
         }else{
            
            double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            double sl = price + StopLossPoints * _Point;
            double tp = price - TakeProfitPoints * _Point;
            
            trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, Lots, price, sl, tp, "Death Cross Entry");
         }
      }
   }
}

//+------------------------------------------------------------------+
//| 检查移动止损条件                                                 |
//+------------------------------------------------------------------+
void CheckTrailingStop()
{
   if(!PositionSelect(_Symbol)) return;

   double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
   double currentSL = PositionGetDouble(POSITION_SL);
   double currentTP = PositionGetDouble(POSITION_TP);
   ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

   if(type == POSITION_TYPE_BUY)
   {
      double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double requiredPrice = openPrice + (TakeProfitPoints * _Point) * 0.5;
      
      if(currentPrice >= requiredPrice && currentSL < openPrice)
      {
         trade.PositionModify(PositionGetInteger(POSITION_TICKET), openPrice, currentTP);
      }
   }
   else if(type == POSITION_TYPE_SELL)
   {
      double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      double requiredPrice = openPrice - (TakeProfitPoints * _Point) * 0.5;
      
      if(currentPrice <= requiredPrice && currentSL > openPrice)
      {
         trade.PositionModify(PositionGetInteger(POSITION_TICKET), openPrice, currentTP);
      }
   }
}
//+------------------------------------------------------------------+